package cn.schoolwow.quickapi.module.business.api.service;

import cn.schoolwow.quickapi.domain.QuickAPIOption;
import cn.schoolwow.quickapi.module.business.api.domain.API;
import cn.schoolwow.quickapi.module.business.api.flow.single.GetByMethodMappingAnnotationFlow;
import cn.schoolwow.quickapi.module.business.api.flow.single.GetByRequestMappingAnnotationFlow;
import cn.schoolwow.quickapi.module.business.api.flow.single.SetAPIDetailFlow;
import cn.schoolwow.quickapi.module.business.api.flow.single.SetAPIResponseBodyFlow;
import cn.schoolwow.quickapi.module.business.apiController.domain.APIController;
import cn.schoolwow.quickapi.module.common.domain.APIDocument;
import cn.schoolwow.quickapi.module.common.flow.GetGenericTypeRecycleClassNameFlow;
import cn.schoolwow.quickapi.module.common.flow.GetRecycleClassNameFlow;
import cn.schoolwow.quickflow.domain.FlowContext;
import cn.schoolwow.quickflow.flow.BusinessFlow;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

public class SetAPIListFlow implements BusinessFlow {
    @Override
    public void executeBusinessFlow(FlowContext flowContext) throws Exception {
        setAPIList(flowContext);
        setReturnEntity(flowContext);
        executeAPIListener(flowContext);
    }

    @Override
    public String name() {
        return "设置API列表复合流程";
    }

    private void setAPIList(FlowContext flowContext){
        APIDocument apiDocument = flowContext.checkInstanceData(APIDocument.class);

        List<API> apiList = new ArrayList<>();
        for(APIController apiController:apiDocument.apiControllerList){
            for(Method method: apiController.clazz.getDeclaredMethods()){
                API api = new API();
                api.method = method;
                api.apiController = apiController;

                flowContext.startFlow(new GetByMethodMappingAnnotationFlow())
                        .next(new GetByRequestMappingAnnotationFlow())
                        .next(new SetAPIDetailFlow())
                        .next(new SetAPIResponseBodyFlow())
                        .putCurrentCompositeFlowData("apiController", apiController)
                        .putCurrentCompositeFlowData("method", method)
                        .putCurrentCompositeFlowData("api", api)
                        .execute();

                apiList.add(api);
            }
        }
        flowContext.putContextData("apiList", apiList);
        apiDocument.apiList = apiList;
    }

    private void setReturnEntity(FlowContext flowContext){
        APIDocument apiDocument = flowContext.checkInstanceData(APIDocument.class);

        for(API api:apiDocument.apiList){
            flowContext.startFlow(new GetRecycleClassNameFlow())
                    .next(new GetGenericTypeRecycleClassNameFlow())
                    .putCurrentCompositeFlowData("rootClazz", api.method.getReturnType())
                    .putCurrentCompositeFlowData("rootType", api.method.getGenericReturnType())
                    .putCurrentCompositeFlowData("classNameSet", api.returnEntityNameList)
                    .execute();
        }
    }

    private void executeAPIListener(FlowContext flowContext){
        QuickAPIOption quickAPIOption = flowContext.checkInstanceData(QuickAPIOption.class);

        if(null==quickAPIOption.apiListener){
            return;
        }
        APIDocument apiDocument = flowContext.checkInstanceData(APIDocument.class);
        for(API api:apiDocument.apiList){
            quickAPIOption.apiListener.handleAPI(api);
        }
    }
}
